package de.hsb.ai.learning;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import weka.core.Instances;
import de.hsb.ai.learning.filter.FugitiveEntryFilter;
import de.hsb.ai.learning.filter.FugitiveEscapeEntryFilter;
import de.hsb.ai.util.ScotlandJadeGameLogger;
import de.hsb.ai.util.ScotlandJadeHelper;
import de.hsb.ai.util.ScotlandJadeGameLogger.Entry;

public class FugitiveAnalysis {

	public static final Logger logger = LoggerFactory.getLogger("sy.analysis");

	public static void main(String[] args) {
		ScotlandJadeGameLogger gameLogger = ScotlandJadeHelper.createGameLogger();
		List<List<Entry>> entries = gameLogger.read();

		if (entries.isEmpty()) {
			logger.warn("no log entries found in " + gameLogger + " exiting");
			return;
		}

		FugitiveEntryFilter[] filters = { 
				new FugitiveEntryFilter("all"), 
//				new FugitiveEntryFilter("chosen", true),
				new FugitiveEscapeEntryFilter("escape")};
		
		Instances[] data = load(entries.iterator(), filters);

		try {
			for (int i = 0; i < filters.length; ++i) {
				logger.info("writing output file for " + filters[i].getName());
				saveInstances(filters[i].getName() + "-moves.arff", data[i]);
			}
		} catch (IOException e) {
			logger.error("writing output file", e);
		}
	}
	
	public static Instances load(Iterator<List<ScotlandJadeGameLogger.Entry>> entryInterator) {
		return load(entryInterator, new FugitiveEntryFilter("all"))[0];
	}

	public static Instances[] load(Iterator<List<ScotlandJadeGameLogger.Entry>> entryInterator, FugitiveEntryFilter... filters) {
		ExecutorService pool = Executors.newFixedThreadPool(6);
		List<Future<FugitiveAnalyzer[]>> results = new LinkedList<Future<FugitiveAnalyzer[]>>();
		while (entryInterator.hasNext()) {
			Replay replay = new Replay(entryInterator.next());
			FugitiveAnalyzer[] analysers = new FugitiveAnalyzer[filters.length];
			for (int i = 0; i < filters.length; ++i) {
				try {
					analysers[i] = new FugitiveAnalyzer(replay.getMap(), replay.getPositions(), filters[i]);
					replay.addListener(analysers[i]);

				} catch (IllegalArgumentException e) {
					logger.error("creating analyzer", e);
				}
			}
			results.add(pool.submit(replay, analysers));
		}
		
		Instances[] data = new Instances[filters.length];

		for (int i = 0; i < filters.length; ++i) {
			Iterator<Future<FugitiveAnalyzer[]>> resultIterator = results.iterator();
			List<Transition> transitions = new LinkedList<Transition>();
			while (resultIterator.hasNext()) {
				try {
					FugitiveAnalyzer[] analyzers = resultIterator.next().get(2, TimeUnit.SECONDS); 
					transitions.addAll(analyzers[i].getTransitions());
				} catch (Exception e) {
					logger.error("getting result", e);
				}
			}
			data[i] = Transition.createInstances("FugitiveMoves", transitions);
		}

		pool.shutdown();

		return data;
	}
	
	private static void saveInstances(String name, Instances data) throws IOException {
		File outputDir = new File(ScotlandJadeHelper.APP_DIR, "weka");
		outputDir.mkdir();
		File outputFile = new File(outputDir, name);

		BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));
		writer.write(data.toString());
		writer.flush();
		writer.close();
	}
}
